using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace TelerikMvcGridCustomBindingHelper.Projections
{
    public interface IProjectionsOptions<TEntity>
    {
        IProjectionsOptions<TEntity> Ignore(Expression<Func<TEntity, object>> selector);
        IProjectionsOptions<TEntity> Include(Expression<Func<TEntity, object>> selector);
        IProjectionsOptions<TEntity> Use(Expression<Func<TEntity, object>> selector);
    }

    public abstract class ProjectionsOptions<TEntity> : IProjectionsOptions<TEntity>
    {
        internal readonly List<Expression> PropertiesToIgnore = new List<Expression>();
        internal readonly List<Expression> PropertiesToInclude = new List<Expression>();
        internal readonly List<Expression> PropertiesToUse = new List<Expression>();

        public IProjectionsOptions<TEntity> Ignore(Expression<Func<TEntity, object>> selector)
        {
            PropertiesToIgnore.Add(selector);
            return this;
        }

        public IProjectionsOptions<TEntity> Include(Expression<Func<TEntity, object>> selector)
        {
            PropertiesToInclude.Add(selector);
            return this;
        }

        public IProjectionsOptions<TEntity> Use(Expression<Func<TEntity, object>> selector)
        {
            PropertiesToUse.Add(selector);
            return this;
        }
    }

    public class ProjectionsOptionsImpl<TEntity> : ProjectionsOptions<TEntity>, ISimpleEquatable
    {
        #region Implementation of ISimpleEquatable

        public string Stringfy()
        {
            var str = GetType().ToString();

            str += PropertiesToUse.Aggregate("\n\tPropertiesToUseOnly: ", (current, expression) => current + string.Join(";", expression.ToString()));

            str += PropertiesToIgnore.Aggregate("\n\tPropertiesToIgnore: ", (current, expression) => current + string.Join(";", expression.ToString()));

            str += PropertiesToInclude.Aggregate("\n\tPropertiesToInclude: ", (current, expression) => current + string.Join(";", expression.ToString()));

            return str;
        }

        public override string ToString()
        {
            return Stringfy();
        }

        #endregion
    }
}